package cn.wjh.business.config;

import cn.wjh.business.domain.vo.YouDaoTranslateResultVo;
import cn.wjh.business.utils.AuthV3Util;
import cn.wjh.business.utils.HttpUtil;
import cn.wjh.common.exception.ServiceException;
import cn.wjh.common.utils.spring.SpringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

@ConfigurationProperties(prefix = "youdao")
@Configuration
@Data
public class YouDaoConfig {
    private String appKey; //应用Id
    private String appSecret; // 应用密钥
    private List<Map<String, String>> appList;
//    状态码映射
    private final Map<String, String> errorCodeMap = new HashMap<String, String>() {{
        put("101", "缺少必填的参数,首先确保必填参数齐全，然后确认参数书写是否正确。");
        put("102", "不支持的语言类型");
        put("103", "翻译文本过长");
        put("104", "不支持的API类型");
        put("105", "不支持的签名类型");
        put("106", "不支持的响应类型");
        put("107", "不支持的传输加密类型");
        put("108", "应用ID无效，注册账号，登录后台创建应用并完成绑定，可获得应用ID和应用密钥等信息");
        put("109", "batchLog格式不正确");
        put("110", "无相关服务的有效应用,应用没有绑定服务应用，可以新建服务应用。注：某些服务的翻译结果发音需要tts服务，需要在控制台创建语音合成服务绑定应用后方能使用。");
        put("111", "开发者账号无效");
        put("112", "请求服务无效");
        put("113", "q不能为空");
        put("114", "不支持的图片传输方式");
        put("116", "strict字段取值无效，请参考文档填写正确参数值");
        put("201", "解密失败，可能为DES,BASE64,URLDecode的错误");
        put("202", "签名检验失败,如果确认应用ID和应用密钥的正确性，仍返回202，一般是编码问题。请确保翻译文本 q 为UTF-8编码");
        put("203", "访问IP地址不在可访问IP列表");
        put("205", "请求的接口与应用的平台类型不一致，确保接入方式（Android SDK、IOS SDK、API）与创建的应用平台类型一致。");
        put("206", "因为时间戳无效导致签名校验失败");
        put("207", "重放请求");
        put("301", "辞典查询失败");
        put("302", "翻译查询失败");
        put("303", "服务端的其它异常");
        put("304", "会话闲置太久超时");
        put("308", "rejectFallback参数错误");
        put("309", "domain参数错误");
        put("310", "未开通领域翻译服务");
        put("401", "账户已经欠费，请进行账户充值");
        put("402", "offlinesdk不可用");
        put("411", "访问频率受限,请稍后访问");
        put("412", "长请求过于频繁，请稍后访问");
        put("1001", "无效的OCR类型");
        put("1002", "不支持的OCR image类型");
        put("1003", "不支持的OCR Language类型");
        put("1004", "识别图片过大");
        put("1201", "图片base64解密失败");
        put("1301", "OCR段落识别失败");
        put("1411", "访问频率受限");
        put("1412", "超过最大识别字节数");
        put("2003", "不支持的语言识别Language类型");
        put("2004", "合成字符过长");
        put("2005", "不支持的音频文件类型");
        put("2006", "不支持的发音类型");
        put("2201", "解密失败");
        put("2301", "服务的异常");
        put("2411", "访问频率受限,请稍后访问");
        put("2412", "超过最大请求字符数");
        put("3001", "不支持的语音格式");
        put("3002", "不支持的语音采样率");
        put("3003", "不支持的语音声道");
        put("3004", "不支持的语音上传类型");
        put("3005", "不支持的语言类型");
        put("3006", "不支持的识别类型");
        put("3007", "识别音频文件过大");
        put("3008", "识别音频时长过长");
        put("3009", "不支持的音频文件类型");
        put("3010", "不支持的发音类型");
        put("3201", "解密失败");
        put("3301", "语音识别失败");
        put("3302", "语音翻译失败");
        put("3303", "服务的异常");
        put("3411", "访问频率受限,请稍后访问");
        put("3412", "超过最大请求字符数");
        put("4001", "不支持的语音识别格式");
        put("4002", "不支持的语音识别采样率");
        put("4003", "不支持的语音识别声道");
        put("4004", "不支持的语音上传类型");
        put("4005", "不支持的语言类型");
        put("4006", "识别音频文件过大");
        put("4007", "识别音频时长过长");
        put("4201", "解密失败");
        put("4301", "语音识别失败");
        put("4303", "服务的异常");
        put("4411", "访问频率受限,请稍后访问");
        put("4412", "超过最大请求时长");
        put("5001", "无效的OCR类型");
        put("5002", "不支持的OCR image类型");
        put("5003", "不支持的语言类型");
        put("5004", "识别图片过大");
        put("5005", "不支持的图片类型");
        put("5006", "文件为空");
        put("5201", "解密错误，图片base64解密失败");
        put("5301", "OCR段落识别失败");
        put("5411", "访问频率受限");
        put("5412", "超过最大识别流量");
        put("9001", "不支持的语音格式");
        put("9002", "不支持的语音采样率");
        put("9003", "不支持的语音声道");
        put("9004", "不支持的语音上传类型");
        put("9005", "不支持的语音识别 Language类型");
        put("9301", "ASR识别失败");
        put("9303", "服务器内部错误");
        put("9411", "访问频率受限（超过最大调用次数）");
        put("9412", "超过最大处理语音长度");
        put("10001", "无效的OCR类型");
        put("10002", "不支持的OCR image类型");
        put("10004", "识别图片过大");
        put("10201", "图片base64解密失败");
        put("10301", "OCR段落识别失败");
        put("10411", "访问频率受限");
        put("10412", "超过最大识别流量");
        put("11001", "不支持的语音识别格式");
        put("11002", "不支持的语音识别采样率");
        put("11003", "不支持的语音识别声道");
        put("11004", "不支持的语音上传类型");
        put("11005", "不支持的语言类型");
        put("11006", "识别音频文件过大");
    }};


    /**
     * 发送请求
     */
    public YouDaoTranslateResultVo sendRequest(String q, String from, String to) throws JsonProcessingException, NoSuchAlgorithmException {
        loadBalancing();//开启负载均衡
        ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
        // 添加请求参数
        Map<String, String[]> params = createYouDaoTranslateRequestParams(q, from, to);
        // 添加鉴权相关参数
        AuthV3Util.addAuthParams(this.appKey, this.appSecret, params);
        // 请求api服务
        byte[] result = HttpUtil.doPost("https://openapi.youdao.com/api", null, params, "application/json");
        // 打印返回结果
        if (result != null) {
            String str = new String(result, StandardCharsets.UTF_8);
            // 转为java对象
            YouDaoTranslateResultVo resultVo = objectMapper.readValue(str, YouDaoTranslateResultVo.class);
            if ("0".equals(resultVo.getErrorCode())) {
                resultVo.setLanguageCode(to);
                return resultVo;
            } else {
                throw new ServiceException(errorCodeMap.get(resultVo.getErrorCode()), resultVo.getErrorCode());
            }
        } else {
            throw new ServiceException("翻译结果不存在！", 400);
        }
    }

    /**
     * 获取请求的参数
     */
    private Map<String, String[]> createYouDaoTranslateRequestParams(String q, String from, String to) {
        return new HashMap<String, String[]>() {{
            put("q", new String[]{q});
            put("from", new String[]{from});
            put("to", new String[]{to});
        }};
    }

    /**
     * 负载均衡 loadBalancing
     * 1.获取app下标
     */
    private int getRandomIndex() {
        int min = 0;
        int max = this.appList.size() > 0 ? this.appList.size() - 1 : 0;//如果长度大于0 减去1 否则会出问题
        Random random = new Random();
        return random.nextInt(max - min + 1) + min;
    }

    /**
     * 负载均衡 loadBalancing
     * 2.设置app
     */
    private void loadBalancing() {
        int index = this.getRandomIndex();
        Map<String, String> appMap = this.appList.get(index);
        this.setAppKey(appMap.get("app-key"));//设置key
        this.setAppSecret(appMap.get("app-secret"));//设置密钥
    }
}
